package com.yxy.springcloud.framework.unionauth.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.yxy.springcloud.framework.common.base.BusinessException;
import com.yxy.springcloud.framework.common.base.PageDataList;
import com.yxy.springcloud.framework.common.base.RestResponse;
import com.yxy.springcloud.framework.common.redis.RedisUtils;
import com.yxy.springcloud.framework.unionauth.DTO.*;
import com.yxy.springcloud.framework.unionauth.dao.*;
import com.yxy.springcloud.framework.unionauth.model.*;
import com.yxy.springcloud.framework.unionauth.utils.TokenCheckUtil;
import com.yxy.springcloud.framework.unionauth.vo.TenantExtend;
import com.yxy.springcloud.framework.unionauth.vo.TenantExtendV2;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.*;

@Slf4j
@Service
public class TenantService {
  @Autowired
  private TokenCheckUtil tokenCheckUtil;

  @Resource
  private RedisUtils redisUtils;

  @Resource
  private TenantMapper tenantMapper;

  @Resource
  private AppTenantMapper appTenantMapper;

  @Resource
  private AppMapper appMapper;

  @Resource
  private TenantAlluserForbiddenMapper tenantAlluserForbiddenMapper;

  public PageDataList<TenantExtend> getList(TenantListDto query) {
    List<TenantExtend> resultList = new ArrayList<>();

    PageHelper.startPage(query.getPageNumber(), query.getPageSize());
    PageHelper.orderBy("t1.create_date desc");//排序
    List<Tenant> dbResult = tenantMapper.selectList(query);
    Page<Tenant> dbResultPage = (Page<Tenant>) dbResult;

    for (Tenant dbItem : dbResultPage.getResult()) {
      Long tenantId = dbItem.getId();
      TenantExtend tenantExtend = new TenantExtend();
      BeanUtils.copyProperties(dbItem, tenantExtend);
      // 查询所属租户组
      long groupId = dbItem.getGroupId();
      if (-1L != groupId) {
        String groupName = tenantMapper.selectByPrimaryKey(groupId).getName();
        tenantExtend.setGroupName(groupName);
      }
      // end
      List<App> appList = tenantMapper.getAppListWithTenant(tenantId);
      tenantExtend.setAppList(appList);
      resultList.add(tenantExtend);
    }

    PageDataList<TenantExtend> pageDataList = new PageDataList<>(dbResultPage.getTotal(),
            dbResultPage.getPages(),
            dbResultPage.getPageNum(), dbResultPage.getPageSize());
    pageDataList.setList(resultList);
    return pageDataList;

  }

  public PageDataList<TenantExtendV2> getList2(TenantListDto query) throws BusinessException {
    List<TenantExtendV2> resultList = new ArrayList<>();

    //租户组条件筛选
    String groupName1 = query.getGroupName();
    if (!StringUtils.isEmpty(groupName1)) {
      Tenant queryObj = new Tenant();
      queryObj.setName(groupName1);
      List<Tenant> tenantGroupList = tenantMapper.select(queryObj);
      if (tenantGroupList.size() != 1) {
        throw new BusinessException(571, "所属租户组不存在或者不唯一");
      }
      query.setGroupId(tenantGroupList.get(0).getId());
    }

    PageHelper.startPage(query.getPageNumber(), query.getPageSize());
    PageHelper.orderBy("t1.create_date desc");//排序
    List<Tenant> dbResult = tenantMapper.selectList(query);
    Page<Tenant> dbResultPage = (Page<Tenant>) dbResult;
    for (Tenant dbItem : dbResultPage.getResult()) {
      Long tenantId = dbItem.getId();
      TenantExtendV2 tenantExtend = new TenantExtendV2();
      BeanUtils.copyProperties(dbItem, tenantExtend);
      // 查询所属租户组
      long groupId = dbItem.getGroupId();
      if (-1L != groupId) {
        String groupName = tenantMapper.selectByPrimaryKey(groupId).getName();
        tenantExtend.setGroupName(groupName);
      }
      // end
      List<App> appList = tenantMapper.getAppListWithTenant(tenantId);
      tenantExtend.setAppList(appList);
      // 查询该tenant是否被禁用所有用户登录app功能
      TenantAlluserForbidden queryObj5 = new TenantAlluserForbidden();
      queryObj5.setTenantId(tenantId);
      TenantAlluserForbidden dbObj = tenantAlluserForbiddenMapper.selectOne(queryObj5);
      if (dbObj == null) {
        tenantExtend.setForbidAllUserLogin(false);
      } else {
        tenantExtend.setForbidAllUserLogin(true);
      }
      resultList.add(tenantExtend);
    }

    PageDataList<TenantExtendV2> pageDataList = new PageDataList<>(dbResultPage.getTotal(),
            dbResultPage.getPages(),
            dbResultPage.getPageNum(), dbResultPage.getPageSize());
    pageDataList.setList(resultList);
    return pageDataList;
  }

  @Transactional(rollbackFor = Exception.class)
  public Map<String, Object> createOrUpdate(TenantCreateDto inputDto) throws BusinessException {
    // 参数合法校验
    String[] selectedAppIdList = inputDto.getSelectedAppIdList();
    if (selectedAppIdList == null || selectedAppIdList.length == 0) {
      throw new BusinessException(501, "需要至少选择一个app");
    }
    // end
    Map<String, Object> resultMap = new HashMap<>();

    String curUserStr = tokenCheckUtil.getUserInfoByToken();
    AuthAdminUser loginUser = JSON.parseObject(curUserStr, AuthAdminUser.class);
    if (loginUser == null) {
      // app后台通过feign调用该接口时,不能按正常的逻辑取得loginUser
      loginUser = new AuthAdminUser();
      loginUser.setId(-1L);
      loginUser.setName("app后台");
    }
    Long id = inputDto.getId();
    if (id == null) { // insert
      // 查询tenant 的name是否已经存在,以保证tenant.name全局唯一
      Tenant queryObj = new Tenant();
      queryObj.setName(inputDto.getName());
      List<Tenant> dbList = tenantMapper.select(queryObj);
      if (dbList.size() > 0) {
        resultMap.put("id", dbList.get(0).getId());
      } else {
        Tenant insertObj = new Tenant();
        BeanUtils.copyProperties(inputDto, insertObj);
        InsertBaseEntity baseEntity = new InsertBaseEntity(loginUser.getId(), loginUser.getName());
        BeanUtils.copyProperties(baseEntity, insertObj);
        tenantMapper.insertUseGeneratedKeys(insertObj);
        resultMap.put("id", insertObj.getId());
        // 创建租户和app的关系
        this.createAppTenantRelation(inputDto, insertObj.getId(), loginUser);
      }
      // end
    } else { // update
      Tenant updateObj = new Tenant();
      BeanUtils.copyProperties(inputDto, updateObj);
      updateObj.setId(id);
      updateObj.setUpdateUserId(loginUser.getId());
      updateObj.setUpdateUserName(loginUser.getName());
      updateObj.setUpdateDate(new Date());
      tenantMapper.updateByPrimaryKeySelective(updateObj);
      resultMap.put("id", id);
      // 修改租户和app 的关系
      // 删除无用的 app和tenant的对应关系
      this.deleteAppTenantRelation(inputDto, id);
      // 创建or更新 app_tenant表
      this.createAppTenantRelation(inputDto, id, loginUser);
    }
    resultMap.put("type", inputDto.getType());
    resultMap.put("groupId", inputDto.getGroupId());
    return resultMap;
  }

  // 创建 app和tenant的对应关系
  private void createAppTenantRelation(TenantCreateDto inputDto, Long tenantId, AuthAdminUser loginUser) {
    // 创建租户和app的关系
    List<AppTenant> insertObjList = new ArrayList<>();
    String[] appIdList = inputDto.getSelectedAppIdList();
    for (int index = 0; index < appIdList.length; index++) {
      String appIdStr = appIdList[index];
      Long appId = Long.parseLong(appIdStr);
      // 查看 app_tenant是否存在, 存在则跳过
      AppTenant queryObj = new AppTenant();
      queryObj.setTenantId(tenantId);
      queryObj.setAppId(appId);
      List<AppTenant> oldItems = appTenantMapper.select(queryObj);
      if (oldItems.size() > 0) {
        continue;
      }
      // end
      AppTenant appTenantInsertObj = new AppTenant();
      appTenantInsertObj.setTenantId(tenantId);
      appTenantInsertObj.setAppId(appId);
      InsertBaseEntity baseEntity = new InsertBaseEntity(loginUser.getId(), loginUser.getName());
      BeanUtils.copyProperties(baseEntity, appTenantInsertObj);
      insertObjList.add(appTenantInsertObj);
    }
    if (insertObjList.size() > 0) {
      appTenantMapper.insertList(insertObjList);
    }
  }

  // 删除过时的 app和tenant的对应关系
  private void deleteAppTenantRelation(TenantCreateDto inputDto, Long tenantId) {
    String[] newAppIdList = inputDto.getSelectedAppIdList();
    tenantMapper.deleteAppTenantRelation(tenantId, newAppIdList);
  }

  @Transactional(rollbackFor = Exception.class)
  public void delete(long id) throws BusinessException {
    // 租户逻辑删除
    String curUserStr = tokenCheckUtil.getUserInfoByToken();
    AuthAdminUser loginUser = JSON.parseObject(curUserStr, AuthAdminUser.class);
    Tenant tenantUpdateObj = new Tenant();
    tenantUpdateObj.setId(id);
    tenantUpdateObj.setStatus(1L);
    tenantUpdateObj.setUpdateUserId(loginUser.getId());
    tenantUpdateObj.setUpdateUserName(loginUser.getName());
    tenantUpdateObj.setUpdateDate(new Date());
    tenantMapper.updateByPrimaryKeySelective(tenantUpdateObj);
    // 删除租户与app的对应关系
    AppTenant deleteObj = new AppTenant();
    deleteObj.setTenantId(id);
    appTenantMapper.delete(deleteObj);
    // 删除租户与 用户的对应关系 todo

  }

  public Tenant getDetailById(long id) {
    Tenant queryObj = new Tenant();
    queryObj.setId(id);
    queryObj.setStatus(0L);
    Tenant dbObj = tenantMapper.selectOne(queryObj);
    return dbObj;
  }

  /**
   * 禁用 or启动 tenant下所有user的登录功能
   *
   * @param flag 可选值: enable(启动所有用户的登录功能) disable(禁用所有用户的登录功能)
   */
  public void forbidAllUserLogin(Long tenantId, String flag) throws BusinessException {
    String curUserStr = tokenCheckUtil.getUserInfoByToken();
    AuthAdminUser loginUser = JSON.parseObject(curUserStr, AuthAdminUser.class);

    TenantAlluserForbidden queryObj = new TenantAlluserForbidden();
    queryObj.setTenantId(tenantId);
    TenantAlluserForbidden dbObj = tenantAlluserForbiddenMapper.selectOne(queryObj);
    if (flag.equals("enable")) {
      if (dbObj != null) {
        tenantAlluserForbiddenMapper.deleteByPrimaryKey(dbObj.getId());
      }
    } else if (flag.equals("disable")) { //禁用所有用户
      if (dbObj == null) {
        TenantAlluserForbidden insertObj = new TenantAlluserForbidden();
        InsertBaseEntity baseEntity = new InsertBaseEntity(loginUser.getId(), loginUser.getName());
        BeanUtils.copyProperties(baseEntity, insertObj);
        insertObj.setTenantId(tenantId);
        tenantAlluserForbiddenMapper.insertUseGeneratedKeys(insertObj);
      }

    }
  }

  @Transactional(rollbackFor = Exception.class)
  public Map<String, Object> createOrUpdate2(TenantCreateDto2 inputDto) throws BusinessException {
    TenantCreateDto inputDtoFinal = new TenantCreateDto();
    BeanUtils.copyProperties(inputDto, inputDtoFinal);
    //将appCode转换成selectedAppIdList
    String appCode = inputDto.getAppCode();
    App queryApp = new App();
    queryApp.setName(appCode);
    App curApp = appMapper.selectOne(queryApp);
    String[] selectedAppIdList = {curApp.getId().toString()};
    inputDtoFinal.setSelectedAppIdList(selectedAppIdList);
    //end
    return this.createOrUpdate(inputDtoFinal);
  }
}
